#pragma once

#include "lockqueue.h"

enum LogLevel
{
    INFO,
    ERROR,
    FATAL
};

class Logger
{
public:
    static Logger &GetInstance();

    // 设置日志级别
    void SetLogLevel(LogLevel level);

    // 往日志队列里写数据
    void Log(const std::string &msg);

    // 获取日志等级
    LogLevel GetLogLevel();

    // 将日志等级转为字符串
    std::string LevelToStr();

private:
    LogLevel m_logLevel;
    LockQueue<std::string> m_lockqueue;

    Logger();
    Logger(const Logger &) = delete;
    Logger(Logger &&) = delete;
    Logger &operator=(const Logger &) = delete;
};

#define LOG_INFO(logmsg, ...)                                                                                                   \
    do                                                                                                                          \
    {                                                                                                                           \
        Logger &logger = Logger::GetInstance();                                                                                 \
        logger.SetLogLevel(INFO);                                                                                               \
        time_t now = time(nullptr);                                                                                             \
        tm *nowTime = localtime(&now);                                                                                          \
        char timeStr[64];                                                                                                       \
        sprintf(timeStr, "%d:%d:%d [%s] -> ", nowTime->tm_hour, nowTime->tm_min, nowTime->tm_sec, logger.LevelToStr().c_str()); \
        char buf[128];                                                                                                          \
        snprintf(buf, 128, logmsg, ##__VA_ARGS__);                                                                              \
        std::string str = std::string(timeStr) + std::string(buf);                                                              \
        logger.Log(str);                                                                                                        \
    } while (0)

#define LOG_ERR(logmsg, ...)                                                                                                    \
    do                                                                                                                          \
    {                                                                                                                           \
        Logger &logger = Logger::GetInstance();                                                                                 \
        logger.SetLogLevel(ERROR);                                                                                              \
        time_t now = ::time(nullptr);                                                                                             \
        tm *nowTime = localtime(&now);                                                                                          \
        char timeStr[64];                                                                                                       \
        sprintf(timeStr, "%d:%d:%d [%s] -> ", nowTime->tm_hour, nowTime->tm_min, nowTime->tm_sec, logger.LevelToStr().c_str()); \
        char buf[128];                                                                                                          \
        snprintf(buf, 128, logmsg, ##__VA_ARGS__);                                                                              \
        std::string str = std::string(timeStr) + std::string(buf);                                                              \
        logger.Log(str);                                                                                                        \
    } while (0)

#define LOG_FATAL(logmsg, ...)                                                                                                  \
    do                                                                                                                          \
    {                                                                                                                           \
        Logger &logger = Logger::GetInstance();                                                                                 \
        logger.SetLogLevel(FATAL);                                                                                              \
        time_t now = time(nullptr);                                                                                             \
        tm *nowTime = localtime(&now);                                                                                          \
        char timeStr[64];                                                                                                       \
        sprintf(timeStr, "%d:%d:%d [%s] -> ", nowTime->tm_hour, nowTime->tm_min, nowTime->tm_sec, logger.LevelToStr().c_str()); \
        char buf[128];                                                                                                          \
        snprintf(buf, 128, logmsg, ##__VA_ARGS__);                                                                              \
        std::string str = std::string(timeStr) + std::string(buf);                                                              \
        logger.Log(str);                                                                                                        \
    } while (0)
